/*****************************************************************************************
This file is a part of Arise library.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

Arise Engine		GuiWindow.cpp

					E-mail:		arise_engine@mail.ru

					Origin by:	DK Engine 0.019,
								dev (avon.dn.ua@gmail.com), Agressor (agress0r@mail.ru)

created:			27.01.2008
last changes:		27.01.2008
*****************************************************************************************/
#include "stdafx.h"

#define GUI_Z_ONTOP_OFFSET 0.0001f


GuiWindow::GuiWindow(	int _id, 
						float x, 
						float y, 
						float w, 
						float h		)
{
}
GuiWindow::~GuiWindow()
{
}


void GuiWindow::Render()
{
}


void GuiWindow::SetupSize(float x, float y, float w, float h) 
{
	rect.x1 = x;
	rect.x2 = x + w;
	rect.y1 = y;
	rect.y2 = y + h;
	
	m_background.v[0].pos.x = x;
	m_background.v[0].pos.y = y;
	m_background.v[0].pos.z = 0;
	//m_background.v[0].color = m_background_color;
	m_background.v[0].tex_coords.x = 0;
	m_background.v[0].tex_coords.y = 0;
	
	m_background.v[1].pos.x = x + w;
	m_background.v[1].pos.y = y;
	m_background.v[1].pos.z = 0;
	//m_background.v[1].color = m_background_color;
	m_background.v[1].tex_coords.x = 0;
	m_background.v[1].tex_coords.y = 0;
	
	m_background.v[2].pos.x = x + w;
	m_background.v[2].pos.y = y + h;
	m_background.v[2].pos.z = 0;
	//m_background.v[2].color = m_background_color;
	m_background.v[2].tex_coords.x = 0;
	m_background.v[2].tex_coords.y = 0;
	
	m_background.v[3].pos.x = x;
	m_background.v[3].pos.y = y + h;
	m_background.v[3].pos.z = 0;
	//m_background.v[3].color = m_background_color;
	m_background.v[3].tex_coords.x = 0;
	m_background.v[3].tex_coords.y = 0;
	
	m_background.tex = 0;
	//m_background.blend = BLEND_ALPHABLEND | BLEND_COLORMUL | BLEND_ZWRITE;
	m_current_selection = -1;
}


void GuiWindow::MoveObjects(float dx, float dy) 
{
	for(	std::vector<GuiObject*>::iterator it = elements.begin(); 
			it != elements.end(); it++	)
				if(*it) (*it)->Move(dx,dy);
}


void GuiWindow::CheckObjectFocus(float cursor_x, float cursor_y) 
{
	for(	std::vector<GuiObject*>::iterator it = elements.begin(); 
			it != elements.end(); it++	)
	{
		if(*it)
		{
			if ((*it)->TestPoint(cursor_x, cursor_y))	
				(*it)->Activate();
			else	
				(*it)->Deactivate();
		}
	}
}


void GuiWindow::SelectObject(int object_id) 
{
	if(object_id < 0)
	{
		log(1, "GuiWindow::SelectObject: illegal value - index %d");
		return;
	}

	for(	std::vector<GuiObject*>::iterator it = elements.begin(); 
			it != elements.end(); it++	)
	{
		if(*it)
		{
			if ((*it)->id == object_id)	
				(*it)->Activate();
			else	
				(*it)->Deactivate();
		}
	}
}


void GuiWindow::SelectNext() 
{
	int start = 0;
	if(m_current_selection >= 0)					start = m_current_selection;
	if(m_current_selection == elements.size()-1)	start = 0;

	for(	std::vector<GuiObject*>::iterator it = elements.begin(); 
			it != elements.end(); it++	)
				if(*it) (*it)->Deactivate();

	for(UINT i = start; i < elements.size(); i++) 
	{
		if(		elements[i]->updatable 
			&&	elements[i]->visible
			&&	i != m_current_selection	) 
		{
			elements[i]->Activate();
			m_current_selection = i;
			return;
		}
	}
}

/*
void GuiWindow::OnTop()
{
	m_background.v[0].pos.z += GUI_Z_ONTOP_OFFSET;
	m_background.v[1].pos.z += GUI_Z_ONTOP_OFFSET;
	m_background.v[2].pos.z += GUI_Z_ONTOP_OFFSET;
	m_background.v[3].pos.z += GUI_Z_ONTOP_OFFSET;
}
*/

void GuiWindow::Add(GuiObject* obj) 
{
	if(!obj) return;

	// moving to window context
	obj->Move(-rect.x1, -rect.y1);
	elements.push_back(obj);

	obj->SetParent(this);
}


void GuiWindow::SetBGColor(DWORD color)
{
	//m_background_color		= color;
	//m_background.v[0].color = m_background_color;
	//m_background.v[1].color = m_background_color;
	//m_background.v[2].color = m_background_color;
	//m_background.v[3].color = m_background_color;
}


bool GuiWindow::IsOverElement(float cursor_x, float cursor_y)
{
	//	false if cursor is over any element, true if over clear background.
	//	use like IsCanMove() behaviour
	for(	std::vector<GuiObject*>::iterator it = elements.begin(); 
			it != elements.end(); it++	)
				if((*it) && (*it)->TestPoint(cursor_x, cursor_y))
					return false;
	return true;
}


//--------------------------- overloads --------------------------------------//


void GuiWindow::Update(float m_delta, float cursor_x, float cursor_y, InputEvent* event)
{
	if(!visible || !enabled) return;
		
	if(TestPoint(cursor_x, cursor_y))			//	if cursor is over window
		CheckObjectFocus(cursor_x, cursor_y);	//	find active element inside		

	for(	std::vector<GuiObject*>::iterator it = elements.begin(); 
			it != elements.end(); it++	)
	{
			if(*it)
			{
				if(!(*it)->updatable || !(*it)->visible) continue;
				//	update valid element (animation, movement, and other)
				(*it)->Update(m_delta, cursor_x, cursor_y, event);	
			}
	}

	//...	update parent \ child here!
}


void GuiWindow::MouseMove(float offset_x, float offset_y)
{
	//	cursor change position. move window or apply changes to all elements 
	
	if(!visible) return;

	for(	std::vector<GuiObject*>::iterator it = elements.begin(); 
			it != elements.end(); it++	)
	{
			if(*it) (*it)->MouseMove(offset_x + rect.x1, offset_y + rect.y1);
	}

	if(active)
	{
		//	if select at this moment, move window with new cursor offset
		float dx = m_pos_x - offset_x;
		float dy = m_pos_y - offset_y;
		Move(dx,dy);
		MoveObjects(dx,dy);
	}
	else
	{
		m_pos_x = offset_x;
		m_pos_y = offset_y;
	}
}


void GuiWindow::KeyEvent(int key_id)
{
	if(visible) 
	{
		for(	std::vector<GuiObject*>::iterator it = elements.begin(); 
				it != elements.end(); it++	)
		{
			if(*it) (*it)->KeyEvent(key_id);
		}

		if(key_id == KEY_TAB) 
		{
			SelectNext();
		}
	}
}


void GuiWindow::Move(float dx, float dy) 
{
	SetupSize(rect.x1-dx, rect.y1-dy, m_width, m_height);
}


void GuiWindow::Enable()
{
	EnableChildren();
	enabled = true;
}


void GuiWindow::Disable()
{
	DisableChildren();
	enabled = false;
}


void GuiWindow::Activate()
{
	Enable(); 
	SetVisible(true);

	SelectObject(0);
}